/*
 * @Author: 赵东选 1807248216@qq.com
 * @Date: 2024-10-20 10:06:05
 * @LastEditors: 赵东选 1807248216@qq.com
 * @LastEditTime: 2024-10-23 17:37:30
 * @FilePath: /9_int/bsp/gpio/bsp_gpio.c
 * @Description:
 *
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
 */
#include "bsp_gpio.h"

void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *config)
{
    if (config->direction == kGPIO_DigitalInput)
    {
        base->GDIR &= ~(1 << pin);
    }
    else
    {
        base->GDIR |= (1 << pin);
        gpio_pinwrite(base, pin, config->outputLogic);
    }
    gpio_intconfig(base, pin, config->direction);
}

void gpio_pinwrite(GPIO_Type *base, int pin, int value)
{
    if (value == 0)
    {
        base->DR &= ~(1 << pin);
    }
    else
    {
        base->DR |= (1 << pin);
    }
}

int gpio_pinread(GPIO_Type *base, int pin)
{
    return ((base->DR >> pin) & 0x1);
}

/* 使得指定IO中断*/
void gpio_enableint(GPIO_Type *base, uint32_t pin)
{
    base->IMR |= (0x1 << pin);
}

/* 禁止指定IO中断*/
void gpio_disableint(GPIO_Type *base, uint32_t pin)
{
    base->IMR &= ~(0x1 << pin);
}

/* 清除中断标志位*/
void gpio_clearintflags(GPIO_Type *base, uint32_t pin)
{
    base->ISR |= (0x1 << pin);
}

/* GPIO中断初始化*/
void gpio_intconfig(GPIO_Type *base, uint32_t pin, gpio_interrupt_mode_t ping_int_mode)
{
    volatile uint32_t *icr = NULL;
    uint32_t icrShift = pin;

    base->EDGE_SEL &= ~(0x1 << pin);

    if (pin < 16)
    {
        icr = &(base->ICR1);
    }
    else
    {
        icr = &(base->ICR2);
        icrShift -= 16;
    }
    switch (ping_int_mode)
    {
    case kGPIO_IntLowLevel:
        *icr &= ~(0x11 << (2 * icrShift));
        break;
    case kGPIO_IntHighLevel:
        *icr &= ~(0x11 << (2 * icrShift));
        *icr |= (0x1 << (2 * icrShift));
        break;
    case kGPIO_IntRisingEdge:
        *icr &= ~(0x11 << (2 * icrShift));
        *icr |= (0x10 << (2 * icrShift));
        break;
    case kGPIO_IntFallingEdge:
        *icr &= ~(3 << (2 * icrShift));
        *icr |= (0x11 << (2 * icrShift));
        break;
    case kGPIO_IntRisingOrFallingEdge:
        base->EDGE_SEL |= (0x1 << pin);
        break;
    default:
        break;
    }
}